//package cn.gyn.gynrpc.core.util;
//
//import org.apache.commons.lang.StringUtils;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.io.Resource;
//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
//import org.springframework.core.io.support.ResourcePatternResolver;
//import org.springframework.core.type.ClassMetadata;
//import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
//import org.springframework.core.type.classreading.MetadataReader;
//import org.springframework.core.type.classreading.MetadataReaderFactory;
//import org.springframework.util.ClassUtils;
//import org.springframework.util.SystemPropertyUtils;
//
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.List;
//import java.util.function.Predicate;
///**
// * Scan packages to return all specific classes.
// * 目前项目里注入BEAN都是依赖spring的注解扫描，这里可以通过spring的ResourcePatternResolver和MetadataReaderFactory扫描机制，
// * 扫描指定的class path,获取到class path下的所有类型，通过断言（相当于一个过滤器）处理某个类（或注解），返回一个集合回去。
// * 比如通过这个扫描机制来获取@GynProvider注解的类，统一进行bean注入（Java进阶训练营第五次课里的自写bean工厂：registerBeanDefinitions），
// * 从而去掉@Component注解，只用@GynProvider注解即可
// */
//public class ScanPackagesUtils {
//    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
//
//    /**
//     *
//     * @param packages
//     * @param predicate 关于断言：https://v.flomoapp.com/mine/?memo_id=MTE1ODkzNzM2
//     * @return
//     */
//    public static List<Class<?>> scanPackages(String[] packages, Predicate<Class<?>> predicate) {
//        List<Class<?>> results = new ArrayList<>();
//        //ResourcePatternResolver根据指定的资源模式，比如类文件或配置文件，获取匹配的资源对象\getResources(String locationPattern)
//        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
//        CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
//        for (String basePackage : packages) {
//            if (StringUtils.isBlank(basePackage)) {
//                continue;
//            }
//            //将给定的basePackage转换为一个类路径中的资源搜索路径，用于查找符合指定条件的资源文件。
//            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
//                    ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage)) +
//                    "/" + DEFAULT_RESOURCE_PATTERN;
//            try {
//                Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
//                for (Resource resource : resources) {
//                    System.out.println(" resource: " + resource.getFilename());
//                    //MetadataReaderFactory用于创建MetadataReader对象:读取类或资源的元数据信息，如类的注解、接口、父类等。
//                    MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
//                    ClassMetadata classMetadata = metadataReader.getClassMetadata();
//                    String className = classMetadata.getClassName();
//                    Class<?> clazz = Class.forName(className);
//                    if(predicate.test(clazz)){
//                        System.out.println(" ===> class: " + className);
//                        results.add(clazz);
//                    }
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        return results;
//    }
//
//    public static void main(String[] args) {
//        String packages = "cn.gyn.gynrpc";
//        System.out.println(" 1.****************");
//        System.out.println(" => scan all classes for packages: " + packages);
//        //这里split的字符是逗号，可以写多个packages
//        List<Class<?>> classes = scanPackages(packages.split(","), p -> true);
//        classes.forEach(System.out::println);
//
//        System.out.println();
//        System.out.println(" 2.*****************");
//        System.out.println(" => scan all classes with @Configuration for packages: " + packages);
//        //断言里判断若类里有注解了@Configuration，返回为true
//        List<Class<?>> classWithConfig = scanPackages(packages.split(","),
//                p -> Arrays.stream(p.getAnnotations()).anyMatch(a -> a.annotationType().equals(Configuration.class)));
//        classWithConfig.forEach(System.out::println);
//        /**
//         * 输出：
//         * class cn.gyn.gynrpc.core.config.ConsumerConfig
//         * class cn.gyn.gynrpc.core.config.ProviderConfig
//         */
//    }
//
//}
